import wx
from twisted.internet import wxreactor
wxreactor.install()

import cPickle
import message
import cardplayer

# import twisted reactor *only after* installing wxreactor
from twisted.internet import reactor, protocol
from twisted.protocols import basic

authed = False

class NoUnsplitter(wx.SplitterWindow):
    def __init__(self, parent, id):
        wx.SplitterWindow.__init__(self, parent, id)
    def Unsplit(self, toRemove):
        self.SetSashPosition(10, True)

class TablePanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.deck_sprite = wx.Bitmap('resources/52_100.png')
        self.felt = wx.Bitmap('resources/felt.png')
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.players = None

    def OnPaint(self, event):
        # Render Table Panel
        dc = wx.PaintDC(self)
        dc.DrawBitmap(self.felt, 0, 0)

#        self.players[0].render_hand(dc, self.deck_sprite, 0)

        try:
            # Render Player
            i = 0
            if self.players:
                for player in self.players:
                    if player:
                        player.render_hand(dc, self.deck_sprite, i)
                    i += 1

        except Exception, ex:
            print ex

    def UpdatePlayers(self, players):
        self.players = players

class ChatFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="Netjack", size=(1000, 800))

        self.protocol = None # twisted Protocol
        self.name = "Unnamed"
        self.players = None

        self.superSizer = wx.BoxSizer(wx.VERTICAL)
        self.splitter = NoUnsplitter(self, -1)
        self.superSizer.Add(self.splitter, 1, wx.EXPAND, 10)
        self.splitter.SetSashSize(25)
        self.splitter.SetMinimumPaneSize(25)

#        self.panelTable = wx.Panel(self.splitter)
        self.panelTable = TablePanel(self.splitter)
        self.panelControl = wx.Panel(self.splitter)

        self.splitter.SplitHorizontally(self.panelTable, self.panelControl)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.innerSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.text = wx.TextCtrl(self.panelControl, style=wx.TE_MULTILINE | wx.TE_READONLY)
        self.ctrl = wx.TextCtrl(self.panelControl, style=wx.TE_PROCESS_ENTER)
        self.txtBet = wx.StaticText(self.panelControl, label="Bet amount:")
        self.spinBet = wx.SpinCtrl(self.panelControl, -1)
        self.spinBet.SetRange(1, 1000000)
        self.spinBet.SetValue(5)

        self.bHit = wx.Button(self.panelControl, -1, "Hit")
        self.bStand = wx.Button(self.panelControl, -1, "Stand")
        self.bBet = wx.Button(self.panelControl, -1, "Set Bet Amount")

        self.bHit.Disable()
        self.bStand.Disable()

        self.sizer.Add(self.text, 5, wx.EXPAND)
        self.sizer.Add(self.ctrl, 0, wx.EXPAND)


        self.innerSizer.Add(self.bHit, 1, wx.EXPAND, 10)
        self.innerSizer.Add(self.bStand, 1, wx.EXPAND, 10)
        self.innerSizer.Add(self.txtBet, 1, wx.EXPAND, 10)
        self.innerSizer.Add(self.spinBet, 1, wx.EXPAND, 10)
        self.innerSizer.Add(self.bBet, 1, wx.EXPAND, 10)
        self.sizer.Add(self.innerSizer, 1, wx.EXPAND)

#        self.SetSizer(self.sizer)

        self.ctrl.Bind(wx.EVT_TEXT_ENTER, self.send)
        self.bHit.Bind(wx.EVT_BUTTON, self.hit)
        self.bStand.Bind(wx.EVT_BUTTON, self.stand)
        # self.bBetMore.Bind(wx.EVT_BUTTON,)
        # self.bBetLess.Bind(wx.EVT_BUTTON,)

        self.panelControl.SetSizer(self.sizer)
        self.ctrl.SetFocus()

#        self.Layout()
#        self.SetAutoLayout(True)
#        self.sizer.Fit(self.superSizer)

        self.SetSizer(self.superSizer)

        self.Layout()
        self.Centre()

    def send(self, evt):
        if authed:
            self.protocol.sendLine(cPickle.dumps(message.Message("chat", str(self.ctrl.GetValue()))) + "\t")
            self.ctrl.SetValue("")
        else:
            self.protocol.sendLine(cPickle.dumps(message.Message("auth", str(self.ctrl.GetValue()))) + "\t")
            self.ctrl.SetValue("")

    def hit(self, evt):
        self.protocol.sendLine(cPickle.dumps(message.Message('hit')))

    def stand(self, evt):
        self.protocol.sendLine(cPickle.dumps(message.Message('stand')))

    def OnFail(self, event):
        dlg = wx.MessageDialog(self, "Unable to connect to server.", "Connection Error", wx.OK)
        dlg.ShowModal()
        dlg.Destroy()
        self.Destroy()

    def DisplayPlayers(self):
        self.panelTable.UpdatePlayers(self.players)
        self.panelTable.Refresh()
#        val = self.text.GetValue()
#        for player in self.players:
#            if player:
#                val += player.name + str(player._get_current_hand()) + '\n'
#        val += '---------------------\n'
#        self.text.SetValue(val)
#        self.text.SetInsertionPointEnd()


    def Enable(self):
        self.bHit.Enable()
        self.bStand.Enable()

    def Disable(self):
        self.bHit.Disable()
        self.bStand.Disable()

class DataForwardingProtocol(basic.LineReceiver):
    def __init__(self):
        self.output = None
        self.lineBuffer = None

    def dataReceived(self, data):
#        print "-----Begin Data Received-----"
        gui = self.factory.gui
#        print "---Begin Raw Receive---\n" + repr(data) + "\n---End Raw Recieve"
        lines = data.rstrip("\t\r\n").split("\t")
        # lines.pop()
        if self.lineBuffer:
            lines[0] = self.lineBuffer + lines[0]
            self.lineBuffer = None
        for stripMe, num in zip(lines, range(len(lines))):
            item = stripMe.strip("\r\n")
#            print "***Begin Pickle #" + str(num + 1) + "***"
#            print repr(item)
#            print "***End Pickle #" + str(num + 1) + "***"
            try:
                undata = cPickle.loads(item)
                if isinstance(undata, message.Message):
                    print type(undata)
                    if undata.type == "chat":
                        gui.protocol = self
                        if gui:
                            val = gui.text.GetValue()
                            gui.text.SetValue(val + undata.payload + "\n------------------------\n")
                            gui.text.SetInsertionPointEnd()
                    elif undata.type == "userStates":
                        self.factory.gui.players = undata.payload
                        self.factory.gui.DisplayPlayers()
                        print self.factory.gui.players
                        for player in self.factory.gui.players:
                            if player:
                                print player.name + "'s turn:" + str(player.myTurn)
                                if player.name == gui.name:
                                    if player.myTurn == True:
                                        gui.Enable()
                                    else:
                                        gui.Disable()

                    elif undata.type == "auth":
                        temp = undata.payload.split(':')
                        if temp[0] == "okay":
                            global authed
                            authed = True
                            gui.name = temp[1]
                else:
                    print "ERROR: Data was not a Message object."
                print "-----End Data Received-----"
#            except (cPickle.UnpicklingError, EOFError) as e:
            except :
                self.lineBuffer = stripMe
                print "Error unpickling network object."
#                print type(e)

    def connectionMade(self):
        self.output = self.factory.gui.text # redirect Twisted's output

    # def connectionFailed(self):
        # frame.OnFail()

class ChatFactory(protocol.ClientFactory):
    def __init__(self, gui):
        self.gui = gui
        self.protocol = DataForwardingProtocol

    def clientConnectionLost(self, transport, reason):
        pass
        # reactor.stop()

    def clientConnectionFailed(self, transport, reason):
        pass
        # reactor.stop()


if __name__ == '__main__':
    app = wx.App(False)
    frame = ChatFrame()
    frame.Show()
    reactor.registerWxApp(app)
    reactor.connectTCP("localhost", 5001, ChatFactory(frame))
    reactor.run()
